#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use std::io::Read;
use std::time::Duration;
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::fmt::time::ChronoLocal;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{Layer, Registry};
use windows::core::{s, w};

pub fn main() -> anyhow::Result<()> {
    let _x = config_tracing_log()?;
    let runtime = tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()?;

    runtime.block_on(async {
        let result = read_serial_port().await;
        if let Err(error) = result {
            log::error!("程序错误 {:?}", error);
        }
    });
    Ok(())
}

#[allow(non_snake_case)]
struct Order {
    orderNo: String,
    verifyCode: String,
}
pub async fn send_request(data: &[u8]) -> anyhow::Result<()> {
    let array = split_u8_array(data, b';');
    log::info!("============={}============= {}",array.0, array.1);
    #[derive(serde::Deserialize, Debug, Clone, Default, serde::Serialize)]
    
    let order = Order {
        orderNo: array.0,
        verifyCode: array.1,
    };
    let client = reqwest::Client::new();
    let response = client.post("https://xp.xianpinlife.com/xpll/order/order/sendVerifyCode").json(&order).send().await?;
    log::info!("发送核销码结果{:?}",response.text().await?);
    Ok(())
}


pub async fn read_serial_port() -> anyhow::Result<()> {
    let ports = serialport::available_ports()?;
    for p in ports {
        log::info!("{}", p.port_name);
    }

    let mut reader_result = serialport::new("COM3", 9600)
        .timeout(Duration::from_secs(3))
        .open();
    match reader_result {
        Ok(mut reader) => {
            unsafe {
                MessageBoxW(None, w!("程序已启动"), w!("鲜品来了小程序扫码程序"), MB_OK);
            }
            let mut buffer = [0; 27];
            loop {
                match reader.read(&mut buffer) {
                    Ok(bytes_read) => {
                        if bytes_read > 0 {
                            log::info!("Read {} bytes: {:?}", bytes_read, &buffer[0..bytes_read]);
                            let result = send_request(&buffer[0..bytes_read]).await;
                            if let Err(error) = result {
                                log::error!("{:?}", error);
                            }
                        }
                    }
                    Err(e) => {}
                }
            }
        }
        Err(error) => {
            anyhow::bail!("{:?}", error)
        }
    }
}


pub fn config_tracing_log() -> anyhow::Result<(WorkerGuard, WorkerGuard)> {
    let timer = ChronoLocal::new("%Y-%m-%d %H:%M:%S%.3f".to_string());

    let (console_appender, guard1) = tracing_appender::non_blocking(std::io::stdout());

    let fmt_layer = tracing_subscriber::fmt::layer()

        .with_timer(timer.clone())
        .with_target(true)
        .with_writer(console_appender)
        .with_ansi(true)
        .json()
        .with_filter(tracing_subscriber::filter::LevelFilter::DEBUG);

    let file_appender = tracing_appender::rolling::daily("./logs", "serial_port");

    let (no_blocking, guard) = tracing_appender::non_blocking(file_appender);
    let file_layer = tracing_subscriber::fmt::layer()
        .with_timer(timer)
        .with_target(true)
        .with_ansi(true)
        .with_writer(no_blocking)
        .json()
        .with_filter(tracing_subscriber::filter::LevelFilter::DEBUG);

    // let subscriber = tracing_subscriber::registry()
    // .with(fmt_layer)
    // .with(file_layer);

    // tracing::subscriber::set_global_default(subscriber)?;

    Registry::default().with(fmt_layer).with(file_layer).init();

    Ok((guard1, guard))
}

fn split_u8_array(data: &[u8], delimiter: u8) -> (String, String) {
    let mut index = 0;
    while index < data.len() && data[index] != delimiter {
        index += 1;
    }
    let first_part = String::from_utf8_lossy(&data[..index]).to_string();
    let second_part = String::from_utf8_lossy(&data[index + 1..]).to_string();
    (first_part, second_part)
}

use windows::Win32::Foundation::HWND;
use windows::Win32::UI::WindowsAndMessaging::{MB_OK, MB_ICONINFORMATION, MessageBoxA, MessageBoxW};
 